﻿using Newtonsoft.Json;
using NLog;
using NLog.Config;
using NLog.Targets;
using NLog.Targets.Wrappers;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Messaging;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using GSMMODEM;

namespace SMSRobot
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        /// <summary>
        /// 短信猫类 封装了 System.IO.Ports.SerialPort
        /// </summary>
        public GsmModem mGsmModem;
        /// <summary>
        /// 短信定时操作
        /// </summary>
        public static System.Timers.Timer SMSTimer;
        /// <summary>
        /// 主窗口的上下文
        /// </summary>
        private MainWinContext mMainWinContext;
        /// <summary>
        /// 短信猫是否已经初始化
        /// </summary>
        private bool IsGMInitialized = false;

        private const string ConsoleTargetName = "LogConsole";
        private Logger _logger;
        private AsyncTargetWrapper _wrapper;

        private AboutBox aboutBox;

        #region 初始化属性

        private EventHandler OnRecievedHandler = null;
        /// <summary>
        /// 是否正在发送中...
        /// </summary>
        private static bool IsSending = false;
        /// <summary>
        /// 进程锁
        /// </summary>
        private static object Lock = new object();

        #endregion

        public MainWindow()
        {
            InitializeComponent();
        }
        #region LOG
        private Logger Logger
        {
            get { return _logger ?? (_logger = LogManager.GetLogger(GetType().Name)); }
        }

        /// <summary>
        /// 窗体初始化以后
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainWindowInitialized(object sender, EventArgs e)
        {
            #region 初始化界面
            aboutBox = new AboutBox();
            this.mMainWinContext = new MainWinContext();
            this.DataContext = mMainWinContext;
            //读取设置文件
            string[] ports = SerialPort.GetPortNames();
            if (ports.Length > 0)
            {
                CmbComPort.ItemsSource = ports;
                CmbComPort.SelectedItem = Properties.Settings.Default.ComPort;
            }
            else
            {
                CmbComPort.SelectedItem = Properties.Settings.Default.ComPort;
            }

            mMainWinContext.AutoStart = Properties.Settings.Default.AutoStart;
            TestPhone.Text = Properties.Settings.Default.TestNumber;
            #endregion

            OnRecievedHandler = new EventHandler(mGsmModem_OnRecieved);

            SMSTimer = new System.Timers.Timer(Properties.Settings.Default.SMSTimeSpan * 1000);
            SMSTimer.Elapsed += new ElapsedEventHandler(OnTimedSMSEvent);
            //SMSTimer.AutoReset = true;

            if (Properties.Settings.Default.AutoStart)
            {
                InitSerialPort();
                OpenSerialPort();
                if (mGsmModem.IsOpen)
                {
                    SMSTimer.Start();
                    mMainWinContext.IsWorking = true;
                    mMainWinContext.IsEnabledWork = false;
                    BtnStart.Content = "停止";
                    Logger.Log(LogLevel.Info, "开始工作");
                }
            }

            #region Set Log Target
            var target = new WpfRichTextBoxTarget
            {
                Name = ConsoleTargetName,
                Layout = "[${longdate:}]${message}",
                //Layout = "${time:}|${threadid:padding=3}|${level:uppercase=true:padding=-5}|${logger:padding=-15}|${message}|${exception}",
                ControlName = Console.Name,
                FormName = Name,
                AutoScroll = true,
                MaxLines = 1000,
                UseDefaultRowColoringRules = true
            };
            _wrapper = new AsyncTargetWrapper
            {
                Name = ConsoleTargetName,
                WrappedTarget = target
            };
            SimpleConfigurator.ConfigureForTargetLogging(_wrapper, LogLevel.Info);
            Logger.Log(LogLevel.Info, "准备就绪!");
            #endregion
        }
        #endregion

        /// <summary>
        /// 初始化串口
        /// </summary>
        public void InitSerialPort()
        {
            string ComPort = Properties.Settings.Default.ComPort;
            int BaudRate = Properties.Settings.Default.BaudRate;
            try
            {
                Logger.Log(LogLevel.Trace, "串口{0},{1}初始化中...", ComPort, BaudRate);
                mGsmModem = new GsmModem(ComPort, BaudRate);
                mGsmModem.AutoDelMsg = true;
                mGsmModem.SmsRecieved += OnRecievedHandler;
                Logger.Log(LogLevel.Trace, "串口{0},{1}初始化完毕!", ComPort, BaudRate);
                IsGMInitialized = true;
            }
            catch (Exception e)
            {
                mGsmModem.SmsRecieved -= OnRecievedHandler;
                //mGsmModem.Close();
                Logger.Log(LogLevel.Error, "串口{0}:{1}", mGsmModem.ComPort, e.Message);
                IsGMInitialized = false;
            }
        }

        /// <summary>
        /// 初始化串口
        /// </summary>
        public void OpenSerialPort()
        {
            if (!mGsmModem.IsOpen)
            {
                bool opend = false;
                string sResult = "";
                try
                {
                    mGsmModem.ComPort = Properties.Settings.Default.ComPort;
                    mGsmModem.BaudRate = Properties.Settings.Default.BaudRate;
                    opend = mGsmModem.Open(out sResult);
                    if (opend)
                    {
                        mMainWinContext.StateText = mGsmModem.ComPort + "," + mGsmModem.BaudRate;
                        mMainWinContext.IsOpend = true;
                        mMainWinContext.IsEnabledOpen = false;
                        BtnOpen.Content = "关闭";
                        Logger.Log(LogLevel.Info, "{0},{1} 打开成功", mGsmModem.ComPort, mGsmModem.BaudRate);
                    }
                }
                catch (Exception ex)
                {
                    if (mGsmModem.IsOpen)
                    {
                        mGsmModem.Close();
                    }
                    mMainWinContext.IsOpend = false;
                    mMainWinContext.IsEnabledOpen = true;
                    Logger.Log(LogLevel.Error, "{0},{1} 打开失败[{2}]", mGsmModem.ComPort, mGsmModem.BaudRate, sResult);
                }
            }
            else//关闭端口
            {
                try
                {
                    mGsmModem.Close();
                    mMainWinContext.StateText = "准备就绪";
                    mMainWinContext.IsOpend = false;
                    mMainWinContext.IsEnabledOpen = true;
                    BtnOpen.Content = "打开";
                    Logger.Log(LogLevel.Info, "{0},{1} 已关闭", mGsmModem.ComPort, mGsmModem.BaudRate);
                }
                catch (Exception ex)
                {
                    Logger.Log(LogLevel.Error, "{0},{1} 关闭失败{2}", mGsmModem.ComPort, mGsmModem.BaudRate, ex.Message);
                }
            }


        }

        void mGsmModem_OnRecieved(object sender, EventArgs e)
        {
            int sMsgIndex = 0;
            DecodedMessage s1 = mGsmModem.ReadNewMsg(out sMsgIndex);//此处引发异常（此处不属于主进程）  须回调函数才能改变此属性
            Logger.Log(LogLevel.Fatal, "收到短信消息:{0}", s1.SmsContent);
        }
        private void OnTimedSMSEvent(object source, ElapsedEventArgs e)
        {
            //Logger.Log(LogLevel.Info, "等待消息!");
            try
            {
                if (mGsmModem != null && mGsmModem.IsOpen)
                {
                    if (!IsSending)
                    {
                        lock (Lock)
                        {
                            try
                            {
                                IsSending = true;
                                //读取MQ
                                using (MessageQueue messageQueue = new MessageQueue(@".\Private$\sms"))
                                {
                                    messageQueue.Formatter = new XmlMessageFormatter(new string[] { "System.String" });//设置消息队列格式化器
                                    Message message = messageQueue.Receive();//接收消息
                                    Sms sms = JsonConvert.DeserializeObject<Sms>((string)message.Body);
                                    mMainWinContext.Recived += 1;
                                    if (!string.IsNullOrEmpty(sms.PhoneNumber) && sms.PhoneNumber.Trim().Length == 11)
                                    {
                                        Logger.Log(LogLevel.Info, "正在发送消息：{0}:{1}", sms.PhoneNumber, sms.SmsContent);
                                        mGsmModem.SendMsg(sms.PhoneNumber.Trim(), sms.SmsContent.Trim());
                                        Logger.Log(LogLevel.Fatal, "已发送消息至：{0}", sms.PhoneNumber);
                                        mMainWinContext.Sent += 1;
                                    }
                                    else
                                    {
                                        Logger.Log(LogLevel.Warn, "电话号码:{0}格式错误,将忽略这条短信。请及时检查更正！", sms.PhoneNumber.Trim());
                                    }
                                }
                                IsSending = false;
                            }
                            catch (Exception ex)
                            {
                                Logger.Log(LogLevel.Error, ex.Message);
                            }
                            finally
                            {
                                IsSending = false;
                            }

                        }
                    }

                }
                else
                {
                    SMSTimer.Stop();
                }
            }
            catch (Exception ex)
            {
                Logger.Log(LogLevel.Error, ex.Message);
                //throw;
            }

        }

        private void BtnOpen_Click(object sender, RoutedEventArgs e)
        {
            if (IsGMInitialized == false)
            {
                InitSerialPort();
            }
            OpenSerialPort();
        }
        /// <summary>
        /// 开始按钮点击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnStart_Click(object sender, RoutedEventArgs e)
        {
            if (mMainWinContext.IsWorking)
            {
                SMSTimer.Stop();
                mMainWinContext.IsWorking = false;
                mMainWinContext.IsEnabledWork = true;
                BtnStart.Content = "启动";
                Logger.Log(LogLevel.Info, "停止工作");
            }
            else
            {
                if (mGsmModem == null || !mGsmModem.IsOpen)
                {
                    InitSerialPort();
                    OpenSerialPort();
                }
                if (mGsmModem.IsOpen)
                {
                    SMSTimer.Start();
                    mMainWinContext.IsWorking = true;
                    mMainWinContext.IsEnabledWork = false;
                    BtnStart.Content = "停止";
                    Logger.Log(LogLevel.Info, "开始工作");
                }

            }
        }

        private void CmbComPort_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            string[] ports = SerialPort.GetPortNames();
            if (ports.Length > 0)
            {
                CmbComPort.ItemsSource = ports;
            }
        }

        private void BtnClear_Click(object sender, RoutedEventArgs e)
        {
            mMainWinContext.Sent = 0;
            mMainWinContext.Recived = 0;
        }
        private void BtnTest_Click(object sender, RoutedEventArgs e)
        {
            string msg = "本消息来自物联网短信管家\n\r当您收到该消息时说明短信发送功能正常。";
            if (mGsmModem != null && mGsmModem.IsOpen)
            {
                if (!string.IsNullOrEmpty(TestPhone.Text) && TestPhone.Text.Trim().Length == 11)
                {
                    Logger.Log(LogLevel.Info, "正在发送测试短信...");
                    try
                    {
                        using (MessageQueue messageQueue = new MessageQueue(@".\Private$\sms"))
                        {
                            Sms sms = new Sms();
                            sms.ID = 0;
                            sms.PhoneNumber = TestPhone.Text;
                            sms.SmsContent = msg;
                            sms.IsSent = 0;
                            sms.Created = DateTime.Now;
                            string json = JsonConvert.SerializeObject(sms);
                            messageQueue.Send(json);
                        }
                    }
                    catch (MessageQueueException ex)
                    {
                        Logger.Log(LogLevel.Error, ex.Message);
                    }
                    //mGsmModem.SendMsg(TestPhone.Text, msg);
                    Logger.Log(LogLevel.Fatal, "已发送测试消息至“{0}”请注意查收！", TestPhone.Text);
                }
                else
                {
                    Logger.Log(LogLevel.Warn, "请输入正确的电话号码!");
                }
            }
            else
            {
                Logger.Log(LogLevel.Warn, "设备端口未打开!");
            }


        }
        private void BtnAbout_Click(object sender, RoutedEventArgs e)
        {
            aboutBox.ShowDialog();
        }

        private void CmbComPort_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            Properties.Settings.Default.ComPort = CmbComPort.SelectedItem.ToString();   //更改设置文件
            Properties.Settings.Default.Save();
        }

        private void CheckBox_Checked(object sender, RoutedEventArgs e)
        {
            if (Cb_AutoStart.IsChecked.HasValue)
            {
                Properties.Settings.Default.AutoStart = true;
                Properties.Settings.Default.Save(); //更改设置文件
            }
        }
        private void CheckBox_UnChecked(object sender, RoutedEventArgs e)
        {
            if (Cb_AutoStart.IsChecked.HasValue)
            {
                Properties.Settings.Default.AutoStart = false;
                Properties.Settings.Default.Save(); //更改设置文件
            }
        }

        private void TestPhone_TextChanged(object sender, TextChangedEventArgs e)
        {
            Properties.Settings.Default.TestNumber = TestPhone.Text;   //更改设置文件
            Properties.Settings.Default.Save();
        }

    }

}
